<?php

namespace App\Libs;

use Exception;

class CompressLibrary
{
    private $src;
    private $image;
    private $imageInfo;
    private $percent;
    private $newWidth;
    private $newHeight;

    /**
     * 图片压缩构造函数
     * 
     * @param string $src 源图路径
     * @param float $percent 压缩比例，默认为1(不压缩)
     */
    public function __construct($src, $percent = 1.0)
    {
        $this->src = $src;
        $this->percent = max(0.1, min(1.0, $percent)); // 限制压缩比例在0.1到1.0之间
    }

    /**
     * 高清压缩图片
     * 
     * @param string|null $scene 压缩场景
     * @param int|null $width 目标宽度
     * @param int|null $height 目标高度
     * @return bool 成功返回true，失败返回false
     */
    public function compressImg($scene = null, $width = null, $height = null)
    {
        try {
            $this->openImage($scene, $width, $height);
            
            // 根据图片类型确定输出函数和质量参数
            $outputFunction = "image" . $this->imageInfo['type'];
            $quality = $this->imageInfo['type'] == 'png' ? 7 : 80;
            
            // 输出图片
            return $outputFunction($this->image, $this->src, $quality);
        } catch (Exception $e) {
            // 记录错误日志
            error_log("图片压缩失败: " . $e->getMessage());
            return false;
        }
    }

    /**
     * 打开并处理图片
     * 
     * @param string|null $scene 压缩场景
     * @param int|null $width 目标宽度
     * @param int|null $height 目标高度
     * @throws Exception 当图片无法打开或处理时抛出异常
     */
    private function openImage($scene, $width, $height)
    {
        // 检查源文件是否存在
        if (!file_exists($this->src)) {
            throw new Exception("源图片文件不存在: " . $this->src);
        }
        
        // 获取图片信息
        $imageInfo = getimagesize($this->src);
        if (!$imageInfo) {
            throw new Exception("无法获取图片信息或图片格式不支持");
        }
        
        $this->imageInfo = [
            'width' => $imageInfo[0],
            'height' => $imageInfo[1],
            'type' => image_type_to_extension($imageInfo[2], false),
            'attr' => $imageInfo[3]
        ];
        
        // 根据场景计算新尺寸
        if ($scene && $scene == 'size' && $width) {
            $this->newWidth = $width;
            $this->newHeight = $height ? $height : ($width / $this->imageInfo['width']) * $this->imageInfo['height'];
        } else {
            $this->newWidth = $this->imageInfo['width'] * $this->percent;
            $this->newHeight = $this->imageInfo['height'] * $this->percent;
        }
        
        // 确保最小尺寸为1像素
        $this->newWidth = max(1, round($this->newWidth));
        $this->newHeight = max(1, round($this->newHeight));
        
        // 创建图像资源
        $createFunction = "imagecreatefrom" . $this->imageInfo['type'];
        if (!function_exists($createFunction)) {
            throw new Exception("不支持图片类型: " . $this->imageInfo['type']);
        }
        
        $this->image = @$createFunction($this->src);
        if (!$this->image) {
            throw new Exception("无法创建图像资源，文件可能已损坏或格式不支持");
        }
        
        // 处理图片
        $this->resizeImage();
    }

    /**
     * 调整图片尺寸
     */
    private function resizeImage()
    {
        // 创建新画布
        $newImage = imagecreatetruecolor($this->newWidth, $this->newHeight);
        
        if (!$newImage) {
            throw new Exception("无法创建新图像资源");
        }
        
        // 处理PNG透明背景
        if ($this->imageInfo['type'] == 'png') {
            imagealphablending($newImage, false);
            imagesavealpha($newImage, true);
            $transparent = imagecolorallocatealpha($newImage, 255, 255, 255, 127);
            imagefilledrectangle($newImage, 0, 0, $this->newWidth, $this->newHeight, $transparent);
        }
        
        // 调整图片尺寸
        imagecopyresampled(
            $newImage, $this->image, 
            0, 0, 0, 0, 
            $this->newWidth, $this->newHeight, 
            $this->imageInfo['width'], $this->imageInfo['height']
        );
        
        // 释放原图资源
        imagedestroy($this->image);
        
        // 更新为新图像资源
        $this->image = $newImage;
    }

    /**
     * 获取图片信息
     * 
     * @return array 图片信息数组
     */
    public function getImageInfo()
    {
        return $this->imageInfo;
    }
    
    /**
     * 获取新图片尺寸
     * 
     * @return array 包含宽度和高度的数组
     */
    public function getNewDimensions()
    {
        return [
            'width' => $this->newWidth,
            'height' => $this->newHeight
        ];
    }

    /**
     * 析构函数 - 清理资源
     */
    public function __destruct()
    {
        if ($this->image && is_resource($this->image)) {
            imagedestroy($this->image);
        }
    }
}
